package com.crx.springbootinit.service.impl;

import cn.hutool.core.bean.BeanUtil;

import cn.hutool.core.collection.CollUtil;

import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.crx.springbootinit.common.WebSocketServer;
import com.crx.springbootinit.exception.ThrowUtils;
import com.crx.springbootinit.model.dto.love.LoveGiveDTO;
import com.crx.springbootinit.model.dto.love.LovePageDTO;
import com.crx.springbootinit.model.dto.page.PageQuery;
import com.crx.springbootinit.model.dto.page.PageVO;
import com.crx.springbootinit.model.entity.Collect;
import com.crx.springbootinit.model.entity.Love;
import com.crx.springbootinit.mapper.LoveMapper;
import com.crx.springbootinit.model.entity.Post;
import com.crx.springbootinit.model.entity.User;
import com.crx.springbootinit.model.vo.love.LoveAndCollectMeVO;
import com.crx.springbootinit.model.vo.love.LoveMyPostVO;
import com.crx.springbootinit.model.vo.love.LovePostListVO;
import com.crx.springbootinit.service.ICollectService;
import com.crx.springbootinit.service.ILoveService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crx.springbootinit.mapper.PostMapper;
import com.crx.springbootinit.service.IUserService;
import com.crx.springbootinit.utils.AuthUtils;
import com.crx.springbootinit.utils.ThreadLocalUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static com.crx.springbootinit.common.ErrorCode.*;
import static com.crx.springbootinit.common.isLoveOrCollect.*;

/**
 * <p>
 * 点赞表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-10-21
 */
@Service
@RequiredArgsConstructor
public class LoveServiceImpl extends ServiceImpl<LoveMapper, Love> implements ILoveService {

    private final PostMapper postMapper;
    private final RedisTemplate redisTemplate;
    private final ICollectService collectService;
    private final IUserService userService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void giveLove(LoveGiveDTO loveGiveDTO) {
        //1.判断时点赞还是取消点赞
        boolean isLove = loveGiveDTO.getIsLove();
        Long userId = loveGiveDTO.getUserId();
        Long postId = loveGiveDTO.getPostId();
        if(userId==null){
            ThrowUtils.throwIf(true,NOT_LOGIN_ERROR,"未登录！请先登录再访问该界面");
        }
        //2.isLove为true时，点赞，isLove为false时，取消点赞
        //3.判断用户是否已经点赞过该帖子
        Post post = postMapper.selectById(postId);
        if (post == null) {
            //如果帖子不存在，则提示用户帖子不存在
            ThrowUtils.throwIf(true,OPERATION_ERROR,"帖子不存在");
        }
        if (isLove) {
            //点赞
            //1.判断用户是否已经点赞过该帖子
            if(isLove(userId, postId)){
                //2.如果已经点赞过，则提示用户已经点赞过该帖子
                ThrowUtils.throwIf(true,OPERATION_ERROR,"您已经点赞过该帖子");
            }
            //3.如果没有点赞过，则插入点赞数据,并通知前端
            Love lovePO = BeanUtil.copyProperties(loveGiveDTO, Love.class);
            Long targetId =post.getUserId();
            if(save(lovePO)){
                try {
                    String nickname = userService.getById(targetId).getNickname();
                    WebSocketServer.sendNotification(targetId,nickname+"点赞了你的帖子");
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            //4.更新post帖子表中的点赞数loveCount(要加上乐观锁)
            LambdaUpdateWrapper<Post> wrapper = new LambdaUpdateWrapper<Post>()
                    .eq(Post::getId, postId)
                    .eq(Post::getLoveCount, post.getLoveCount());
            postMapper.updateGiveLoveCount(wrapper);


        } else {
            //取消点赞
            //1.判断用户是否已经点赞过该帖子
            if(!isLove(userId, postId)){
                //2.如果没有点赞过，则提示用户没有点赞过该帖子
                ThrowUtils.throwIf(true,OPERATION_ERROR,"您没有点赞过该帖子");
            }
            //3.如果已经点赞过，则删除点赞数据
            remove(new LambdaQueryWrapper<Love>().eq(Love::getUserId, userId).eq(Love::getPostId, postId));
            //4.更新post帖子表中的点赞数loveCount
            LambdaUpdateWrapper<Post> wrapper = new LambdaUpdateWrapper<Post>()
                    .eq(Post::getId, postId)
                    .eq(Post::getLoveCount, post.getLoveCount());
            postMapper.updateCancelLoveCount(wrapper);
        }
    }

    @Override
    public List<LoveMyPostVO> queryWhoLoveMyPostList(String token) {
        //1.根据token从redis中获取用户id
        Long userId= AuthUtils.getUserId(redisTemplate,token);
        LambdaQueryWrapper<Post> queryWrapper = new LambdaQueryWrapper<Post>()
                .eq(Post::getUserId, userId);
        List<Post> postList = postMapper.selectList(queryWrapper);
        if(CollUtil.isEmpty(postList)){
            return Collections.emptyList();
        }
        List<Long> postIdList = postList.stream().map(Post::getId).collect(Collectors.toList());
        //根据帖子的id列表获取点赞列表(非空判断)
        List<Love> loveList = lambdaQuery().in(Love::getPostId, postIdList).list();
        if(CollUtil.isEmpty(loveList)){
            return Collections.emptyList();
        }
        //转换成vo列表返回
        List<LoveMyPostVO> loveMyPostVOList = BeanUtil.copyToList(loveList, LoveMyPostVO.class);
        return loveMyPostVOList;
    }

    @Override
    public List<LovePostListVO> queryMyLovePostList(String token) {
        //1.根据token从redis中获取用户id
        Long userId= AuthUtils.getUserId(redisTemplate,token);
        List<Love> loveList = lambdaQuery().eq(Love::getUserId, userId).list();
        if(CollUtil.isEmpty(loveList)){
            return Collections.emptyList();
        }
        List<Long> postIdList = loveList.stream().map(Love::getPostId).collect(Collectors.toList());
        //3.根据帖子的id列表查询帖子列表
        LambdaQueryWrapper<Post> queryWrapper = new LambdaQueryWrapper<Post>()
                .in(Post::getId, postIdList);
        List<Post> postList = postMapper.selectList(queryWrapper);
        List<LovePostListVO> postVOList = BeanUtil.copyToList(postList, LovePostListVO.class);
        return postVOList;
    }

    @Override
    public Long getLoveMyCount(String token) {
        //1.根据token从redis中获取用户id
        Long userId= AuthUtils.getUserId(redisTemplate,token);
        LambdaQueryWrapper<Post> queryWrapper = new LambdaQueryWrapper<Post>()
                .eq(Post::getUserId, userId);
        List<Post> postList = postMapper.selectList(queryWrapper);
        if(CollUtil.isEmpty(postList)){
            return 0L;
        }
        List<Long> postIdList = postList.stream().map(Post::getId).collect(Collectors.toList());
        //根据帖子的id列表获取点赞列表(非空判断)
        List<Love> loveList = lambdaQuery().in(Love::getPostId, postIdList).list();
        return (long) loveList.size();
    }

    @Override
    public Long getLoveMyCountByUserId(Long userId) {
        //1.根据token从redis中获取用户id
        LambdaQueryWrapper<Post> queryWrapper = new LambdaQueryWrapper<Post>()
                .eq(Post::getUserId, userId);
        List<Post> postList = postMapper.selectList(queryWrapper);
        if(CollUtil.isEmpty(postList)){
            return 0L;
        }
        List<Long> postIdList = postList.stream().map(Post::getId).collect(Collectors.toList());
        //根据帖子的id列表获取点赞列表(非空判断)
        List<Love> loveList = lambdaQuery().in(Love::getPostId, postIdList).list();
        return (long) loveList.size();
    }

    @Override
    public Long getLoveAndCollectCont(String token) {
        Long total=collectService.getCollectMyCount(token)+getLoveMyCount(token);
        return total;
    }

    @Override
    public Long getLoveAndCollectContByUserId(Long userId) {
        Long total=collectService.getCollectMyCountByUserId(userId)+getLoveMyCountByUserId(userId);
        return total;
    }


    @Override
    public PageVO<LoveMyPostVO> queryCollectPage(LovePageDTO lovePageDTO) {
        Integer pageNo = lovePageDTO.getPageNo();
        Integer pageSize = lovePageDTO.getPageSize();
        String nickname = lovePageDTO.getNickname();
        String title = lovePageDTO.getTitle();
        Page<Love> page = new Page<>(pageNo, pageSize);
        lambdaQuery()
                .like(StringUtils.isNotBlank(nickname), Love::getNickname, nickname)
                .like(StringUtils.isNotBlank(title), Love::getTitle, title)
                .orderByDesc(Love::getCreateTime)
                .page(page);
        return PageVO.of(page, LoveMyPostVO.class);
    }

    @Override
    public PageVO<LoveAndCollectMeVO> queryLoveAndCollectMe(PageQuery pageQuery) {
        Integer pageNo = pageQuery.getPageNo();
        Integer pageSize = pageQuery.getPageSize();
        Long userId = ThreadLocalUtil.get("userId");
        LambdaQueryWrapper<Post> wrapper = new LambdaQueryWrapper<Post>()
                .eq(Post::getUserId, userId);
        List<Post> postList = postMapper.selectList(wrapper);
        if (CollUtil.isEmpty(postList)) {
            return new PageVO<>(0L, 0L, Collections.emptyList());
        }
        List<Long> postIdList = postList.stream().map(Post::getId).collect(Collectors.toList());
        Page<Love> lovePage =lambdaQuery()
                .in(Love::getPostId, postIdList)
                .page(new Page<>(pageNo, pageSize));
        Page<Collect> collectPage = collectService.lambdaQuery()
                .in(Collect::getPostId, postIdList)
                .page(new Page<>(pageNo, pageSize));
        // 3. 构建 LoveAndCollectMeVO 列表
        List<LoveAndCollectMeVO> loveAndCollectMeVOList = new ArrayList<>(lovePage.getRecords().size() + collectPage.getRecords().size());

        // 转换 loveList 为 LoveAndCollectMeVO 列表
        if (CollUtil.isNotEmpty(lovePage.getRecords())) {
            List<LoveAndCollectMeVO> loveVOList = lovePage.getRecords().stream().map(love -> {
                LoveAndCollectMeVO loveAndCollectMeVO = new LoveAndCollectMeVO();
                loveAndCollectMeVO.setId(love.getId());
                loveAndCollectMeVO.setPostId(love.getPostId());
                Post post = postMapper.selectById(love.getPostId());
                User userById = userService.getById(love.getUserId());
                loveAndCollectMeVO.setAvatar(userById.getAvatar());
                String imageListStr = post.getImageList();  // 获取图片列表字符串
                List<String> imageList = new ArrayList<>();
                if (imageListStr != null && !imageListStr.isEmpty()) {
                    // 使用 Fastjson 解析 JSON 字符串为 List<String>
                     imageList = JSON.parseArray(imageListStr, String.class);
                }
                loveAndCollectMeVO.setImageUrl(imageList.get(0));
                loveAndCollectMeVO.setUserId(love.getUserId());
                loveAndCollectMeVO.setNickname(love.getNickname());
                loveAndCollectMeVO.setCreateTime(love.getCreateTime().format(DateTimeFormatter.ofPattern("MM-dd")));
                loveAndCollectMeVO.setIsLoveOrCollect(IS_LOVE.getMessage());
                return loveAndCollectMeVO;
            }).collect(Collectors.toList());
            loveAndCollectMeVOList.addAll(loveVOList);
        }

        // 转换 collectList 为 LoveAndCollectMeVO 列表
        if (CollUtil.isNotEmpty(collectPage.getRecords())) {
            List<LoveAndCollectMeVO> collectVOList = collectPage.getRecords().stream().map(collect -> {
                LoveAndCollectMeVO loveAndCollectMeVO = new LoveAndCollectMeVO();
                loveAndCollectMeVO.setId(collect.getId());
                loveAndCollectMeVO.setPostId(collect.getPostId());
                Post post = postMapper.selectById(collect.getPostId());
                User userById = userService.getById(collect.getUserId());
                loveAndCollectMeVO.setAvatar(userById.getAvatar());
                String imageListStr = post.getImageList();  // 获取图片列表字符串
                List<String> imageList = new ArrayList<>();
                if (imageListStr != null && !imageListStr.isEmpty()) {
                    // 使用 Fastjson 解析 JSON 字符串为 List<String>
                    imageList = JSON.parseArray(imageListStr, String.class);
                }
                loveAndCollectMeVO.setImageUrl(imageList.get(0));
                loveAndCollectMeVO.setUserId(collect.getUserId());
                loveAndCollectMeVO.setNickname(collect.getNickname());
                loveAndCollectMeVO.setCreateTime(collect.getCreateTime().format(DateTimeFormatter.ofPattern("MM-dd")));
                loveAndCollectMeVO.setIsLoveOrCollect(IS_COLLECT.getMessage());
                return loveAndCollectMeVO;
            }).collect(Collectors.toList());
            loveAndCollectMeVOList.addAll(collectVOList);
        }
        // 4. 对 LoveAndCollectMeVO 列表按时间降序排序
        List<LoveAndCollectMeVO> sortedList = loveAndCollectMeVOList.stream()
                .sorted(Comparator.comparing(LoveAndCollectMeVO::getCreateTime).reversed())
                .collect(Collectors.toList());

        // 5. 封装分页信息
        PageVO<LoveAndCollectMeVO> pageVO = new PageVO<>();
        pageVO.setTotal(lovePage.getTotal() + collectPage.getTotal());
        pageVO.setPages((pageVO.getTotal() + pageSize - 1) / pageSize);
        pageVO.setList(sortedList);

        return pageVO;
    }

    @Override
    public Boolean isLove(Long userId, Long postId) {
        boolean exists = lambdaQuery().eq(Love::getUserId, userId).eq(Love::getPostId, postId).exists();
        return exists;
    }

}
